/*
 * @描述: 
 * @创建者: kilomChou
 * @Date: 2021-04-11 18:47:43
 * @最后编辑: kilomChou
 * @LastEditTime: 2021-05-06 08:49:34
 */

import IConn from "../../common/core/net/IConn";
import ProtoDispatcher from "../../common/core/net/ProtoDispatcher";
import { ProtoVo } from "../../common/data/Proto";

/** 通信连接 用来跟逻辑端/服务端通信 */
export default class ConnCls implements IConn {

    /** 单例 */
    private constructor() { }
    /** 实例 */
    static readonly ins = new ConnCls();

    readonly PD = new ProtoDispatcher();
    id: number;
    isLocal: boolean;
    socket: WebSocket;

    /** 连接服务端 */
    connServer(url: string, onSucc: () => void, onFail: () => void) {
        try {
            let socket = this.socket = new WebSocket(url);
            socket.binaryType = "arraybuffer";
            socket.onerror = e => onFail();
            socket.onopen = e => {
                console.log("连接服务器成功...");

                socket.onclose = e => {
                    console.log("与服务器断开连接...");
                }
                socket.onmessage = e => {
                    //协议通信
                    let { protocol, data } = ProtoVo.fromBytes(new Uint8Array(e.data));
                    this.onMsg(protocol, data);
                }
                onSucc();
            }
        } catch { onFail(); }
    }

    /** 监听协议 */
    on<Proto extends keyof ProtoVo.Def>(proto: Proto, cb: (data: ProtoVo.Def[Proto]) => any): void {
        this.PD.on(proto, cb);
    }

    /** 接收到协议 */
    onMsg<Proto extends keyof ProtoVo.Def>(proto: Proto, data?: ProtoVo.Def[Proto]): void {
        this.PD.onMsg(proto, data);
    }

    /** 发送协议 */
    send<Proto extends keyof ProtoVo.Def>(proto: Proto, data?: ProtoVo.Def[Proto]): void {
        if (this.isLocal) {
            this.PD.onMsg(proto, data);
        } else {
            this.socket.send(ProtoVo.toBytes(proto, data));
        }
    }
}

/** 通信连接 用来跟逻辑端/服务端通信 */
export const Conn = ConnCls.ins;